
#include <png.h>
#include <BImage>
#include "ReadWrite_png.h"

ReadWrite_png::ReadWrite_png()
{
	_author = "zym";
	_description = "This is BWE Plugin for reading *.png image file, write width libpng.";
	_version = "1.0";
}
ReadWrite_png::~ReadWrite_png()
{

}

const BString& ReadWrite_png::author() const
{
	return _author;
}
const BString& ReadWrite_png::version() const
{
	return _version;
}
const BString& ReadWrite_png::description() const
{
	return _description;
}
const BString& ReadWrite_png::log() const
{
	return _log;
}

BObject* ReadWrite_png::readObject(const BString& fileName)
{
	FILE* fp = fopen(fileName.cstr(), "rb");
	if(!fp)
		return 0;

	png_byte header[8];
	fread(header, 1, 8, fp);
	bool is_png = !png_sig_cmp(header, 0, 8);
	if(!is_png)
	{
		fclose(fp);
		return 0;
	}

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if(!png_ptr)
	{
		fclose(fp);
		return 0;
	}

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, 0, 0);
		fclose(fp);
		return 0;
    }

	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);

	//png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
	png_read_info(png_ptr, info_ptr);

	int width            = png_get_image_width(png_ptr, info_ptr);
    int height           = png_get_image_height(png_ptr, info_ptr);
    int bit_depth        = png_get_bit_depth(png_ptr, info_ptr);
    int color_type       = png_get_color_type(png_ptr, info_ptr);
    int filter_method    = png_get_filter_type(png_ptr, info_ptr);
    int compression_type = png_get_compression_type(png_ptr, info_ptr);
    int interlace_type   = png_get_interlace_type(png_ptr, info_ptr);
	int channels = png_get_channels(png_ptr, info_ptr);
	int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);

	Format format = Format_None;
	switch (color_type)
	{
	case PNG_COLOR_TYPE_PALETTE:
		format = Format_None;
		break;
	case PNG_COLOR_TYPE_RGB:
		format = Format_RGB;
		break;
	case PNG_COLOR_TYPE_RGBA:
		format = Format_RGBA;
		break;
	case PNG_COLOR_TYPE_GRAY:
		format = Format_Alpha;
		break;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
		format = Format_Gray_Alpha;
		break;
	}
	if (!format)
	{
		png_destroy_read_struct(&png_ptr, 0, 0);
		fclose(fp);
		return 0;
	}

	BHolder<BByteArray> pixels = new BByteArray(rowbytes * height);
	BByte* data = pixels->data();
	BArray<BByte*> row_pointers(height);
	for(int i = 0; i < height; i++)
		row_pointers[i] = &data[rowbytes * i];

	png_read_image(png_ptr, row_pointers.data());

	BImage* image = new BImage();
	image->setWidth(width);
	image->setHeight(height);
	image->setPixels(pixels.ptr());
	image->setFormat(format);

	fclose(fp);
	return image;
}
bool ReadWrite_png::writeObject(const BObject* object, const BString& fileName)
{
	return true;
}
